/* 
 * Copyright 2011 Carnegie Mellon University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.cmu.lti.dimple;

import java.io.File;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import edu.cmu.lti.dimple.data.MSParaphrasePair;
import edu.cmu.lti.dimple.data.ComplexQAEvalPair;
import edu.cmu.lti.dimple.data.RTEPair;
import edu.cmu.lti.dimple.data.TermLoader;
import edu.cmu.lti.dimple.mavuno.JudgedParaphrases;
import edu.cmu.lti.dimple.mavuno.LearnedParaphrases;
import edu.cmu.lti.dimple.mavuno.MavunoDataLoader;
import edu.cmu.lti.dimple.nlp.AbstractNLPTool;
import edu.cmu.lti.dimple.nlp.EnglishNLP;

/**
 * A class that contains the main method to reproduce the TextInfer 2011 paper experiment.
 * 
 * @author Hideki Shima
 *
 */
public class TextInfer2011Experiment {

  private List<RTEPair> rtePairs = null; 
  private List<ComplexQAEvalPair> qaPairs = null;
  private List<MSParaphrasePair> msrpcPairs = null;
  private File termFile = new File(Parameters.resourceDir,"terms/verb_list_textinfer2011.txt");
  
  public TextInfer2011Experiment() {
    File logDir = new File("target/logs");
    if (logDir.exists()) {
      for (File f : logDir.listFiles()) {
        f.delete();
      }
    }
    File targetDir = new File("target");
    if (targetDir.exists()) {
      for (File f : targetDir.listFiles()) {
        f.delete();
      }
    }
    new File("target/logs").mkdirs();
  }
  
  private void verify() {
    File resourceDir = Parameters.resourceDir;
    if (!resourceDir.exists() || resourceDir.listFiles().length<6) {
      System.err.println("ERROR: Data are missing in 'resources' directory.");
      System.err.println("Please download them following the instructions at http://code.google.com/p/dimple");
      System.exit(-1);
    }
  }
  
  public void run() {
    verify();
    File[] resultFiles = new File(Parameters.resourceDir,"mavuno-paraphrases").listFiles();
    File fEval = new File(Parameters.resourceDir,"mavuno-annotations/"+(Parameters.isLenient?"lenient":"strict")+"-filtered.annotations");

    JudgedParaphrases jp = MavunoDataLoader.loadAnnotatedParaphrases(fEval);
    List<LearnedParaphrases> lps = new ArrayList<LearnedParaphrases>();
    List<File> resultFileList = new ArrayList<File>();
    for (File f : resultFiles) {
      if (f.getName().startsWith(".")) continue; 
      lps.add( MavunoDataLoader.loadLearnedParaphrases(f) );
      resultFileList.add(f);
    }
    
    AbstractNLPTool nlpTool = new EnglishNLP();
    DimpleAlgorithm dimple = new DimpleAlgorithm( nlpTool );
    ExpectedPrecisionAlgorithm ep = new ExpectedPrecisionAlgorithm();
    ExtrinsicTaskLauncher extrinsic = new ExtrinsicTaskLauncher();
    
    List<String> terms = TermLoader.loadTerms( termFile );
    
//    List<String> terms = new ArrayList<String>();
//    terms.add("to win");
//    terms.add("killed");
//    terms.add("fighting");
//    terms.add("found");
//    terms.add("accused");
//    terms.add("lead");
//    terms.add("reached");
    
    NumberFormat nf = NumberFormat.getNumberInstance();
    nf.setMaximumFractionDigits(4);
    nf.setMinimumFractionDigits(4);
    
    String header = String.format("%-30s", "learner")+ "\tMSRPC\tRTE\tQA\tEP\tEPR\tnCG\n";
    FileUtils.writeFile(header, new File("target/result-small01.txt"));
    FileUtils.writeFile(header, new File("target/result-small05.txt"));
    FileUtils.writeFile(header, new File("target/result-small10.txt"));
    
    for ( String targetTerm : terms ) {
      //Extrinsic
      List<Double> eMSRPC1  = extrinsic.calcExtrinsicMSRPC( msrpcPairs, lps, targetTerm, 1 );
      List<Double> eMSRPC5  = extrinsic.calcExtrinsicMSRPC( msrpcPairs, lps, targetTerm, 5 );
      List<Double> eMSRPC10 = extrinsic.calcExtrinsicMSRPC( msrpcPairs, lps, targetTerm, 10 );
      List<Double> eRTE1  = extrinsic.calcExtrinsicRTE( rtePairs, lps, targetTerm, 1 );
      List<Double> eRTE5  = extrinsic.calcExtrinsicRTE( rtePairs, lps, targetTerm, 5 );
      List<Double> eRTE10 = extrinsic.calcExtrinsicRTE( rtePairs, lps, targetTerm, 10 );
      List<Double> eQA1  = extrinsic.calcExtrinsicQA( qaPairs, lps, targetTerm, 1 );
      List<Double> eQA5  = extrinsic.calcExtrinsicQA( qaPairs, lps, targetTerm, 5 );
      List<Double> eQA10 = extrinsic.calcExtrinsicQA( qaPairs, lps, targetTerm, 10 );
  
      //Intrinsic
      List<Double> ap10    = ep.calcEP( lps, jp, targetTerm, 10, true, false );
      List<Double> ePrec1  = ep.calcEP( lps, jp, targetTerm, 1, false, false );
      List<Double> ePrec5  = ep.calcEP( lps, jp, targetTerm, 5, false, false );
      List<Double> ePrec10 = ep.calcEP( lps, jp, targetTerm, 10, false, false );
      List<Double> ePrecR1 = ep.calcEP( lps, jp, targetTerm, 1, false, true ); //doesn't score redundant pair
      List<Double> ePrecR5 = ep.calcEP( lps, jp, targetTerm, 5, false, true );
      List<Double> ePrecR10= ep.calcEP( lps, jp, targetTerm, 10, false, true );
      List<Double> nDCG    = dimple.calculateDimple( lps, jp, targetTerm, 10, true );
      List<Double> nCG1    = dimple.calculateDimple( lps, jp, targetTerm, 1, false );
      List<Double> nCG5    = dimple.calculateDimple( lps, jp, targetTerm, 5, false );
      List<Double> nCG10   = dimple.calculateDimple( lps, jp, targetTerm, 10, false );
      
      StringBuilder lTable = new StringBuilder();
      lTable.append(String.format("%-20s", "learner")+ "\t");
      lTable.append("MSRPC1\tMSRPC5\tMSRPC10\tRTE1\tRTE5\tRTE10\tQA1\tQA5\tQA10\tAP\tEP1\tEP5\tEP10\tEPR1\tEPR5\tEPR10\tnDCG\tnCG1\tnCG5\tnCG10\t\n");
      StringBuilder s1 = new StringBuilder();
      StringBuilder s5 = new StringBuilder();
      StringBuilder s10 = new StringBuilder();
      
      for (int i = 0; i < resultFileList.size(); i++) {
        try {
          String alg = resultFileList.get(i).getName().replaceAll("\\.results", "");
          boolean selected = alg.matches("bcb|bcb-s|br|pd-gigaword");
          if (selected) {
            alg += "*";
            String th = String.format("%-30s", "\"" + targetTerm + "\"_" + alg) + "\t";
            s1.append(th);
            s5.append(th);
            s10.append(th);
          }
          lTable.append(String.format("%-20s", alg) + "\t");
          genCell(lTable, s1,   nf, selected, eMSRPC1.get(i));
          genCell(lTable, s5,   nf, selected, eMSRPC5.get(i));
          genCell(lTable, s10,  nf, selected, eMSRPC10.get(i));
          genCell(lTable, s1,   nf, selected, eRTE1.get(i));
          genCell(lTable, s5,   nf, selected, eRTE5.get(i));
          genCell(lTable, s10,  nf, selected, eRTE10.get(i));
          genCell(lTable, s1,   nf, selected, eQA1.get(i));
          genCell(lTable, s5,   nf, selected, eQA5.get(i));
          genCell(lTable, s10,  nf, selected, eQA10.get(i));
          genCell(lTable, null, nf, selected, ap10.get(i));
          genCell(lTable, s1,   nf, selected, ePrec1.get(i));
          genCell(lTable, s5,   nf, selected, ePrec5.get(i));
          genCell(lTable, s10,  nf, selected, ePrec10.get(i));
          genCell(lTable, s1,   nf, selected, ePrecR1.get(i));
          genCell(lTable, s5,   nf, selected, ePrecR5.get(i));
          genCell(lTable, s10,  nf, selected, ePrecR10.get(i));
          genCell(lTable, null, nf, selected, nDCG.get(i));
          genCell(lTable, s1,   nf, selected, nCG1.get(i));
          genCell(lTable, s5,   nf, selected, nCG5.get(i));
          genCell(lTable, s10,  nf, selected, nCG10.get(i));
          lTable.append("\n");
          if (selected) {
            s1.append("\n");
            s5.append("\n");
            s10.append("\n");
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
      System.out.println(s5);
      FileUtils.appendFile(lTable.toString(), new File("target/result-large.txt"));
      FileUtils.appendFile(s1.toString(), new File("target/result-small01.txt"));
      FileUtils.appendFile(s5.toString(), new File("target/result-small05.txt"));
      FileUtils.appendFile(s10.toString(), new File("target/result-small10.txt"));
      
      System.out.println(lTable);
    }
    
    StringBuilder pairSize = new StringBuilder();
    List<String> pairSizeLog = new ArrayList<String>(extrinsic.getSizeLog());
    Collections.sort(pairSizeLog);
    for ( String s : pairSizeLog ) {
      pairSize.append(s+"\n");
    }
    FileUtils.appendFile(pairSize.toString(), new File("target/pair_size.txt"));
  }
  
  private static void genCell( StringBuilder large, StringBuilder small, 
          NumberFormat nf, boolean isSelected, double s ) {
    if ( Double.isNaN(s) ) s = 0;
    if (large!=null) large.append( nf.format(s)+"\t" );
    if (small!=null && isSelected) small.append( nf.format(s)+"\t" );
  }

  public static void main(String[] args) {
    new TextInfer2011Experiment().run();
  }
  
}
